package com.zcn.io.web.utils;

import lombok.Data;

import java.util.concurrent.*;

/**
 * @desc:
 * @author: 202438 邱建伟
 * @date: 2024/11/3 16:16
 * @Copyright (c) 2024, 江苏金恒信息科技股份有限公司
 */

public class SingleThreadExecutor {
    private final ExecutorService executorService;
    private final BlockingQueue<Runnable> taskQueue;
    private volatile boolean isRunning = false;

    private final static int DEFAULT_QUEUE_CAPACITY = 10;

    public SingleThreadExecutor() {
        this(DEFAULT_QUEUE_CAPACITY);
    }

    public SingleThreadExecutor(int queueCapacity) {
        this.taskQueue = new LinkedBlockingQueue<>(queueCapacity);
        this.executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "SingleThreadExecutor-Thread");
                thread.setDaemon(true); // Daemon thread to allow JVM to shut down gracefully
                return thread;
            }
        });

        // Start the internal task runner
        startInternalRunner();
    }

    private void startInternalRunner() {
        executorService.submit(() -> {
            while (true) {
                try {
                    Runnable task = taskQueue.take();
                    if (task != null) {
                        isRunning = true;
                        try {
                            task.run();
                        } finally {
                            isRunning = false;
                        }
                    }
                } catch (InterruptedException e) {
                    isRunning = false;
                    Thread.currentThread().interrupt();
                }
            }
        });
    }

    public void execute(Runnable task) {
        try {
            taskQueue.put(task);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Task submission interrupted", e);
        }
    }

    public void shutdown() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public boolean isRunning() {
        return isRunning;
    }
}

